package com.ruibang.glass.equipment.service.impl.device;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruibang.glass.common.constants.Constants;
import com.ruibang.glass.common.constants.RedisKey;
import com.ruibang.glass.common.domain.camunda.BpmProcessInstanceCreate;
import com.ruibang.glass.common.domain.camunda.BpmProcessInstanceStatus;
import com.ruibang.glass.common.domain.camunda.BpmTaskApproveReq;
import com.ruibang.glass.common.domain.file.FileBusiness;
import com.ruibang.glass.equipment.domain.req.RepairPlanReq;
import com.ruibang.glass.equipment.entity.device.RepairPerson;
import com.ruibang.glass.equipment.entity.device.RepairPlan;
import com.ruibang.glass.equipment.feign.CamundaApi;
import com.ruibang.glass.equipment.feign.FileApi;
import com.ruibang.glass.equipment.mapper.device.RepairPlanMapper;
import com.ruibang.glass.equipment.service.CommonService;
import com.ruibang.glass.equipment.service.RepairPlanService;
import com.teaming.cloud.framework2.autoconfigure.redis.RedisSingleService;
import com.teaming.cloud.framework2.common.constant.CommonConstant;
import com.teaming.cloud.framework2.common.model.ResultBody;
import com.teaming.cloud.framework2.common.pojo.PageRequest;
import com.teaming.cloud.framework2.common.pojo.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
public class RepairPlanServiceImpl extends ServiceImpl<RepairPlanMapper, RepairPlan> implements RepairPlanService {

    @Autowired
    private CommonService commonService;

    @Autowired
    private CamundaApi camundaApi;

    @Autowired
    private FileApi fileApi;

    @Autowired
    private RedisSingleService redisService;


    private static final String REPAIR_WORK_FLOW = "repair_work_flow";//方案/标准作业流程
    private static final String REPAIR_STOP_MACHINE = "repair_stop_machine";//停机挂牌单
    private static final String REPAIR_SAFETY = "repair_safety";//安全交底
    private static final String REPAIR_FINAL_REPORT = "repair_final_report"; //总结报告附件


    @Override
    public PageResult<RepairPlan> queryPage(PageRequest<RepairPlanReq> pageRequest) {
        final RepairPlanReq param = pageRequest.getParam();
        final LambdaQueryWrapper<RepairPlan> lambda = new QueryWrapper<RepairPlan>().lambda();
        this.buildCondition(lambda,param);
        if(param!=null){
            if(CommonConstant.TWO_STR.equals(param.getBusinessStage())){
                List<String> nodes = new ArrayList<>();
                nodes.add("Activity_076n957");
                nodes.add("Activity_1av92uq");
                nodes.add("Activity_005lqdm");
                nodes.add("Activity_1xe7wdq");
                lambda.in(RepairPlan::getProcessNode,nodes);
            }else if (CommonConstant.THREE_STR.equals(param.getBusinessStage())){
                List<String> nodes = new ArrayList<>();
                nodes.add("Activity_1av92uq");
                nodes.add("Activity_005lqdm");
                nodes.add("Activity_1xe7wdq");
                lambda.in(RepairPlan::getProcessNode,nodes);
            }
        }
        final IPage<RepairPlan> page = this.page(new Page<>(pageRequest.getPageNo(), pageRequest.getPageSize()), lambda);

        if(page!=null&& CollectionUtils.isNotEmpty(page.getRecords())){
            List<String> businessKeys = page.getRecords().stream().map(RepairPlan::getRepairId).collect(Collectors.toList());
            //获取业务流程状态
            ResultBody<List<BpmProcessInstanceStatus>> resultBody = camundaApi.queryProcessInstanceStatus(businessKeys);
            Map<String, BpmProcessInstanceStatus> processMap = null;
            Map<String,FileBusiness> fileBusinessMap = null;
            if (resultBody != null && CollectionUtils.isNotEmpty(resultBody.getData())) {
                processMap = resultBody.getData().stream().collect(Collectors.toMap(BpmProcessInstanceStatus::getBusinessKey, b->b, (s1, s2) -> s1));
            }
            ResultBody<List<FileBusiness>> fileBusinessesRs = fileApi.getFileBusinessByIds(businessKeys);
            if (resultBody != null && CollectionUtils.isNotEmpty(resultBody.getData())) {
                fileBusinessMap = fileBusinessesRs.getData().stream().collect(Collectors.toMap(FileBusiness::getBusinessId,fb->fb,(f1,f2)->f1));
            }

            Map<Object, Object> userMap = redisService.hmget(RedisKey.USER_GROUP_TYPE);

            List<RepairPerson> repairPersons = baseMapper.getWorkPerson(businessKeys);
            Map<String, List<RepairPerson>> repairPersonMap = null;
            if(CollectionUtils.isNotEmpty(repairPersons)){
                repairPersons.forEach(rp->{
                    if(StringUtils.isNotBlank(rp.getUserId())){
                        rp.setUserName(userMap.get(rp.getUserId())==null?"":userMap.get(rp.getUserId()).toString());
                    }
                });
                repairPersonMap = repairPersons.stream().collect(Collectors.groupingBy(RepairPerson::getRepairId));
            }
            Map<Object, Object> areaMap = redisService.hmget(RedisKey.AREA_GROUP_TYPE);
            for (RepairPlan record : page.getRecords()) {
                if(userMap!=null){
                    record.setProjectLeaderName(userMap.get(record.getProjectLeader())==null?"":userMap.get(record.getProjectLeader()).toString());
                }
                if(areaMap!=null){
                    record.setAreaName(areaMap.get(record.getArea())==null?"":areaMap.get(record.getArea()).toString());
                }

                if(repairPersonMap!=null){
                   List<RepairPerson> person = repairPersonMap.get(record.getRepairId());
                   if(CollectionUtils.isNotEmpty(person)){
                       record.setWorkPerson(person.stream().map(p->p.getUserId()).collect(Collectors.toList()));
                       record.setWorkPersonNames(person.stream().map(p->p.getUserName()).collect(Collectors.toList()));
                   }
                }

                if (processMap != null) {
                    BpmProcessInstanceStatus process = processMap.get(record.getRepairId());
                    if(process!=null) {
                        record.setStatus(process.getStatus());
                        record.setProcessId(process.getProcessInstanceId());
                        record.setCurrentUser(process.getUserId());
                        record.setNodeName(process.getNodeName());
                        if (param != null) {
                            if (CommonConstant.TWO_STR.equals(param.getBusinessStage())) {
                                if (CollectionUtils.isNotEmpty(record.getWorkPerson())) {
                                    record.setCurrentUser(null);
                                }
                            }else if(CommonConstant.ONE_STR.equals(param.getBusinessStage())){
                                if(!("Activity_0f9dxwi".equals(record.getProcessNode()))){
                                    record.setCurrentUser(null);
                                }
                            }
                        }
                    }
                }
                if(fileBusinessMap!=null){
                    FileBusiness fileBusiness = fileBusinessMap.get(record.getRepairId().concat(REPAIR_WORK_FLOW));
                    if(fileBusiness!=null){
                        record.setWorkFlowFiles(fileBusiness.getFileIds());
                    }
                    fileBusiness = fileBusinessMap.get(record.getRepairId().concat(REPAIR_STOP_MACHINE));
                    if(fileBusiness!=null){
                        record.setStopMachineFiles(fileBusiness.getFileIds());
                    }
                    fileBusiness = fileBusinessMap.get(record.getRepairId().concat(REPAIR_SAFETY));
                    if(fileBusiness!=null){
                        record.setSafetyFiles(fileBusiness.getFileIds());
                    }
                    fileBusiness = fileBusinessMap.get(record.getRepairId().concat(REPAIR_FINAL_REPORT));
                    if(fileBusiness!=null){
                        record.setFinalReportFiles(fileBusiness.getFileIds());
                    }
                }
            }

        }

        PageResult<RepairPlan> pr = new PageResult(page);
        return pr;
    }

    @Override
    public RepairPlan getDetail(String repairId) {
        RepairPlan repairPlan = baseMapper.selectById(repairId);
        if(repairPlan!=null){
            ResultBody<List<FileBusiness>> fileBusinessesRs = fileApi.getFileBusinessByIds(Arrays.asList(repairId));
            if(fileBusinessesRs!=null&&CollectionUtils.isNotEmpty(fileBusinessesRs.getData())){
                Map<String,FileBusiness> fileBusinessMap = fileBusinessesRs.getData().stream().collect(Collectors.toMap(f1->f1.getBusinessId(),fb->fb,(f1,f2)->f1));
                FileBusiness fileBusiness = fileBusinessMap.get(repairPlan.getRepairId().concat(REPAIR_WORK_FLOW));
                if(fileBusiness!=null){
                    repairPlan.setWorkFlowFiles(fileBusiness.getFileIds());
                }
                fileBusiness = fileBusinessMap.get(repairPlan.getRepairId().concat(REPAIR_STOP_MACHINE));
                if(fileBusiness!=null){
                    repairPlan.setStopMachineFiles(fileBusiness.getFileIds());
                }
                fileBusiness = fileBusinessMap.get(repairPlan.getRepairId().concat(REPAIR_SAFETY));
                if(fileBusiness!=null){
                    repairPlan.setSafetyFiles(fileBusiness.getFileIds());
                }
                fileBusiness = fileBusinessMap.get(repairPlan.getRepairId().concat(REPAIR_FINAL_REPORT));
                if(fileBusiness!=null){
                    repairPlan.setFinalReportFiles(fileBusiness.getFileIds());
                }
            }
        }

        return repairPlan;
    }

    /**
     * 构造查询条件
     * @param lambda
     * @param param
     */
    private void buildCondition(LambdaQueryWrapper<RepairPlan> lambda, RepairPlanReq param){
        lambda.eq(RepairPlan::getIsDelete, CommonConstant.ZERO_STR);
        if(null == param) return;
        if(StringUtils.isNotBlank(param.getProjectName())){
            lambda.like(RepairPlan::getProjectName, param.getProjectName());
        }
        if(StringUtils.isNotBlank(param.getArea())){
            lambda.eq(RepairPlan::getArea, param.getArea());
        }

        if(StringUtils.isNotBlank(param.getDeviceName())){
            lambda.eq(RepairPlan::getDeviceName, param.getDeviceName());
        }

        if(StringUtils.isNotBlank(param.getProfessionalId())){
            lambda.eq(RepairPlan::getProfessionalId, param.getProfessionalId());
        }

        if(StringUtils.isNotBlank(param.getContractor())){
            lambda.like(RepairPlan::getContractor, param.getContractor());
        }

        if(StringUtils.isNotBlank(param.getProjectLeaderName())){
            lambda.like(RepairPlan::getProjectLeaderName, param.getProjectLeaderName());
        }

        if(StringUtils.isNotBlank(param.getConfirmPersonName())){
            lambda.like(RepairPlan::getConfirmPersonName, param.getConfirmPersonName());
        }

        if(param.getPlannedStartTime()!=null&&param.getPlannedEndTime()!=null){
            lambda.ge(RepairPlan::getPlannedStartTime, param.getPlannedStartTime());
            lambda.le(RepairPlan::getPlannedStartTime, param.getPlannedEndTime());
        }
        if(param.getActualFinishStartTime()!=null&&param.getActualFinishEndTime()!=null){
            lambda.ge(RepairPlan::getActualFinishTime, param.getActualFinishStartTime());
            lambda.le(RepairPlan::getActualFinishTime, param.getActualFinishEndTime());
        }

        if(param.getActualStartTime()!=null&&param.getActualEndTime()!=null){
            lambda.ge(RepairPlan::getActualStartTime, param.getActualStartTime());
            lambda.le(RepairPlan::getActualStartTime, param.getActualEndTime());
        }


        lambda.orderBy(true,false, RepairPlan::getCreateTime);
    }


    @Override
    public ResultBody updateOrAdd(RepairPlan repairPlan) {
        if (StringUtils.isBlank(repairPlan.getRepairId())) {
            repairPlan.setApproveStatus(CommonConstant.ZERO_STR);
            repairPlan.setIsDelete(CommonConstant.ZERO_STR);
            baseMapper.insert(repairPlan);

            //方案/标准作业流程
            if(CollectionUtils.isNotEmpty(repairPlan.getWorkFlowFiles())){
                FileBusiness fileBusiness = new FileBusiness();
                fileBusiness.setFileIds(repairPlan.getWorkFlowFiles());
                fileBusiness.setBusinessId(repairPlan.getRepairId());
                fileBusiness.setAttribute(REPAIR_WORK_FLOW);
                fileApi.updateBusinessById(fileBusiness);
            }


            //停机挂牌单
            if(CollectionUtils.isNotEmpty(repairPlan.getStopMachineFiles())){
                FileBusiness fileBusiness = new FileBusiness();
                fileBusiness.setFileIds(repairPlan.getStopMachineFiles());
                fileBusiness.setBusinessId(repairPlan.getRepairId());
                fileBusiness.setAttribute(REPAIR_STOP_MACHINE);
                fileApi.updateBusinessById(fileBusiness);
            }
            //安全交底
            if(CollectionUtils.isNotEmpty(repairPlan.getSafetyFiles())){
                FileBusiness fileBusiness = new FileBusiness();
                fileBusiness.setFileIds(repairPlan.getSafetyFiles());
                fileBusiness.setBusinessId(repairPlan.getRepairId());
                fileBusiness.setAttribute(REPAIR_SAFETY);
                fileApi.updateBusinessById(fileBusiness);
            }
            //总结报告附件
            if(CollectionUtils.isNotEmpty(repairPlan.getFinalReportFiles())){
                FileBusiness fileBusiness = new FileBusiness();
                fileBusiness.setFileIds(repairPlan.getFinalReportFiles());
                fileBusiness.setBusinessId(repairPlan.getRepairId());
                fileBusiness.setAttribute(REPAIR_FINAL_REPORT);
                fileApi.updateBusinessById(fileBusiness);
            }

            BpmProcessInstanceCreate instanceCreate = new BpmProcessInstanceCreate();
            instanceCreate.setBusinessKey(repairPlan.getRepairId());
            instanceCreate.setMenuId(repairPlan.getMenuId());
            //发起流程
            Map<String, Object> variables = new HashMap<>();
            variables.put(Constants.PROCESS_INSTANCE_STARTER_USER_ID, commonService.getUser().getUserId());
            variables.put(Constants.PROCESS_INSTANCE_BUSINESS_KEY, repairPlan.getRepairId());
            variables.put(Constants.PROCESS_INSTANCE_MENU_ID, repairPlan.getMenuId());
            instanceCreate.setVariables(variables);

            String processId = commonService.startProcess(instanceCreate);

            ResultBody<String> resultBody = camundaApi.getProcessNodeById(processId);
            if(resultBody!=null&&StringUtils.isNotBlank(resultBody.getData())){
                repairPlan.setProcessNode(resultBody.getData());
            }
            baseMapper.updateById(repairPlan);
            //直接通过第一流程节点
            if (StringUtils.isNotBlank(processId)) {
                BpmTaskApproveReq bpmTaskApproveReq = new BpmTaskApproveReq();
                bpmTaskApproveReq.setId(processId);
                bpmTaskApproveReq.setUserId(commonService.getUser().getUserId());
                camundaApi.approve(bpmTaskApproveReq);
            }

            return ResultBody.success();
        }
        //作业人员
        if(CollectionUtils.isNotEmpty(repairPlan.getWorkPerson())){
            baseMapper.saveWorkPerson(repairPlan.getWorkPerson(),repairPlan.getRepairId());
        }

        //删除业务对应文件信息
        fileApi.deleteByBusinessId(repairPlan.getRepairId());

        //方案/标准作业流程
        if(CollectionUtils.isNotEmpty(repairPlan.getWorkFlowFiles())){
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setFileIds(repairPlan.getWorkFlowFiles());
            fileBusiness.setBusinessId(repairPlan.getRepairId());
            fileBusiness.setAttribute(REPAIR_WORK_FLOW);
            fileApi.updateBusinessById(fileBusiness);
        }


        //停机挂牌单
        if(CollectionUtils.isNotEmpty(repairPlan.getStopMachineFiles())){
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setFileIds(repairPlan.getStopMachineFiles());
            fileBusiness.setBusinessId(repairPlan.getRepairId());
            fileBusiness.setAttribute(REPAIR_STOP_MACHINE);
            fileApi.updateBusinessById(fileBusiness);
        }
        //安全交底
        if(CollectionUtils.isNotEmpty(repairPlan.getSafetyFiles())){
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setFileIds(repairPlan.getSafetyFiles());
            fileBusiness.setBusinessId(repairPlan.getRepairId());
            fileBusiness.setAttribute(REPAIR_SAFETY);
            fileApi.updateBusinessById(fileBusiness);
        }
        //总结报告附件
        if(CollectionUtils.isNotEmpty(repairPlan.getFinalReportFiles())){
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setFileIds(repairPlan.getFinalReportFiles());
            fileBusiness.setBusinessId(repairPlan.getRepairId());
            fileBusiness.setAttribute(REPAIR_FINAL_REPORT);
            fileApi.updateBusinessById(fileBusiness);
        }
        baseMapper.updateById(repairPlan);
        return ResultBody.success();
    }

    @Override
    public void delete(String id) {
        lambdaUpdate().eq(RepairPlan::getRepairId,id).set(RepairPlan::getIsDelete, Constants.ONE_STR).update();
    }

    @Override
    public void batchDelete(List<String> ids) {
        baseMapper.batchDelete(ids);
    }

}
